package com.qth.valet.controller;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qth.valet.common.annotation.Logs;
import com.qth.valet.common.annotation.Release;
import com.qth.valet.common.annotation.RepeatSubmit;
import com.qth.valet.common.theadlocal.UserOrDriverIdHolder;
import com.qth.valet.common.utils.*;
import com.qth.valet.common.rouyi.DjApiProperties;
import com.qth.valet.common.rouyi.FileUploadUtils;
import com.qth.valet.common.rouyi.SpringUtils;
import com.qth.valet.entity.po.*;
import com.qth.valet.entity.vo.ChildrenDriverVo;
import com.qth.valet.entity.vo.IncomesVo;
import com.qth.valet.entity.vo.OrdersPending;
import com.qth.valet.service.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/qth/driver")
public class DriverController {

    private final DriversService driversService;

    private final OrdersService ordersService;

    private final OrderHistoryService orderHistoryService;

    private final DriversReviewService driversReviewService;

    private final DriverBalanceDetailService driverBalanceDetailService;

    private final NoticeDriverService noticeDriverService;

    @Logs(operation = "更新司机状态")
    @PostMapping("/updateSts")
    public ResponseResult<Void> updateSts(@RequestBody Driver driver) {
        boolean update = driversService.updateSts(UserOrDriverIdHolder.getDriverId(), driver.getStatus());
        if (!update) {
            return ResponseResult.fail("更新司机状态失败，请联系管理员。");
        }
        return ResponseResult.success("更新司机状态成功。");
    }

    @GetMapping("/getOrderPool")
    public ResponseResult<List<OrdersPending>> getOrder(Double longitude, Double latitude) {
        //Page<OrdersPending> page = new Page<>(pageNum, pageSize);
        List<OrdersPending> pendingOrder = ordersService.getPendingOrder(longitude, latitude, StatusConstants.ORDER_WAIT);
        return ResponseResult.success(pendingOrder);
    }


    @Logs(operation = "司机抢单")
    @PostMapping("/grabOrder")
    public ResponseResult<Void> grabOrder(@RequestParam String orderId) {
        return ordersService.grabOrder(UserOrDriverIdHolder.getDriverId(), orderId);
    }

    //@Logs(operation = "根据司机id获取订单")
    @GetMapping("/getAllOrder")
    public ResponseResult<IPage<Orders>> getAllOrder(Integer status,
                                                     @RequestParam(defaultValue = "1") int pageNum,
                                                     @RequestParam(defaultValue = "10") int pageSize) {
        Page<Orders> page = new Page<>(pageNum, pageSize);
        return ResponseResult.success(ordersService.getAllOrder(UserOrDriverIdHolder.getDriverId(), page, status));
    }

    @Logs(operation = "司机取消订单")
    @PostMapping("/cancel")
    public ResponseResult<Void> cancel(@RequestBody Orders orders) {
        LambdaUpdateWrapper<Orders> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(Orders::getStatus, StatusConstants.ORDER_WAIT)
                .set(Orders::getDriverId, null)
                .eq(Orders::getId, orders.getId());
        boolean update = ordersService.update(updateWrapper);
        if (!update) {
            return ResponseResult.fail("司机取消订单失败，请联系客服！");
        }
        driversService.updateSts(orders.getDriverId(), StatusConstants.DRIVER_OFFLINE);

        orderHistoryService.saveOrderHistory(orders.getId(), null, orders.getDriverId(), "司机取消订单");
        return ResponseResult.success("司机取消订单");
    }

    /**
     * 通用上传请求（单个）
     */
    @Logs(operation = "上传图片")
    @PostMapping("/upload")
    @Release
    public ResponseResult<String> uploadFile(MultipartFile file) {
        try {
            // 上传文件路径
            String filePath = SpringUtils.getBean(DjApiProperties.class).getUploadPath();
            // 上传并返回新文件名称
            String fileUrl = FileUploadUtils.upload(filePath, file);
            //String url = serverConfig.getUrl() + fileUrl;

            return ResponseResult.success("图片上传成功", fileUrl);
        } catch (Exception e) {
            return ResponseResult.fail(e.getMessage());
        }
    }

    @Logs(operation = "司机注册")
    @PostMapping("/register")
    @RepeatSubmit
    @Release
    public ResponseResult<String> register(@RequestBody Driver reqDriver) {
//        boolean flag = driversService.checkVerifyCode(reqDriver.getPhone(), reqDriver.getVerifyCode());
//        if (!flag) {
//            return ResponseResult.fail("验证码错误或已过期，请重新输入");
//        }

        LambdaQueryWrapper<Driver> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Driver::getPhone, reqDriver.getPhone());
        Driver one = driversService.getOne(queryWrapper);
        if (one != null) {
            return ResponseResult.fail("当前手机号已注册");
        }

        Driver driver = new Driver();
        driver.setPhone(reqDriver.getPhone());
        driver.setPid(reqDriver.getPid() == null ? 0 : reqDriver.getPid());
        driver.setStatus(StatusConstants.DRIVER_OFFLINE);
        driver.setAuditStatus(StatusConstants.DRIVER_RECEIVE_WAIT);
        driversService.save(driver);
        StpUtil.login(driver.getId(), LoginTypeConstants.DRIVER);
        if (driver.getPid() != 0) {
            // 创建一条通知
            noticeDriverService.save(new NoticeDriver()
                    .setDriverId(driver.getPid())
                    .setType(StatusConstants.NOTICE_NEW_CHILD)
                    .setContent("手机尾号“" + CommonUtil.getPhoneSuffix(driver.getPhone(), 4) + "”的用户成功注册成为您的下线")
            );
            // 将司机的通知读取状态改为未读
            driversService.updateNoticeReadStatus(driver.getPid(), false);
        }
        return ResponseResult.success("注册成功", StpUtil.getTokenValue());
    }

    @Logs(operation = "司机登录")
    @PostMapping("/login")
    @Release
    public ResponseResult<String> login(@RequestBody Driver drivers) {
//        boolean flag = driversService.checkVerifyCode(drivers.getPhone(), drivers.getVerifyCode());
        boolean flag = true;
        if (flag) {
            LambdaQueryWrapper<Driver> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Driver::getPhone, drivers.getPhone());

            Driver one = driversService.getOne(queryWrapper);
            if (one == null) {
                return ResponseResult.fail("当前手机号未注册");
            } else if (StatusConstants.DRIVER_RECEIVE_DISABLE == one.getAuditStatus()) {
                return ResponseResult.fail("当前账号已被禁用，请联系客服");
            }
            // 登录
            StpUtil.login(one.getId(), LoginTypeConstants.DRIVER);
            return ResponseResult.success("登录成功", StpUtil.getTokenValue());
        }

        return ResponseResult.fail("验证码错误或已过期");
    }

    @Logs(operation = "司机账号注销")
    @PostMapping("/logoff")
    /*用token注销司机用户防篡改，正式环境才用*/
    public ResponseResult<String> logoff() {
        Integer driverId = UserOrDriverIdHolder.getDriverId();
        if (driverId == null) {
            return ResponseResult.fail("账号未登录或账号已过期");
        }

        Driver driver = driversService.getById(driverId);
        if (driver == null) {
            return ResponseResult.fail("用户不存在");
        }

        // 删除审核记录
        LambdaQueryWrapper<DriverReview> reviewWrapper = new LambdaQueryWrapper<>();
        reviewWrapper.eq(DriverReview::getDriverId, driverId);
        driversReviewService.remove(reviewWrapper);
        // 删除金额记录
        LambdaQueryWrapper<DriverBalanceDetail> balanceWrapper = new LambdaQueryWrapper<>();
        balanceWrapper.eq(DriverBalanceDetail::getDriverId, driverId);
        driverBalanceDetailService.remove(balanceWrapper);
        //删除司机记录
        boolean b = driversService.removeById(driverId);
        if (!b) {
            return ResponseResult.fail("注销失败，请联系客服");
        }
        StpUtil.logout(driverId); //注销后，即使用户还持有未过期的 Token，也会因为会话已被清除而无法访问需要登录的接口
        return ResponseResult.success();
    }
    /* 传司机id来注销用户，用于测试===========================================*/
//    public ResponseResult<String> logoff(@RequestBody Map<String, Integer> params) { // 接收前端传递的id
//        Integer driverId = params.get("id");
//        if (driverId == null) {
//            return ResponseResult.fail("司机ID不能为空");
//        }
//
//        Driver driver = driversService.getById(driverId);
//        if (driver == null) {
//            return ResponseResult.fail("用户不存在");
//        }
//
//        // 删除审核记录
//        LambdaQueryWrapper<DriverReview> reviewWrapper = new LambdaQueryWrapper<>();
//        reviewWrapper.eq(DriverReview::getDriverId, driverId);
//        driversReviewService.remove(reviewWrapper);
//        // 删除金额记录
//        LambdaQueryWrapper<DriverBalanceDetail> balanceWrapper = new LambdaQueryWrapper<>();
//        balanceWrapper.eq(DriverBalanceDetail::getDriverId, driverId);
//        driverBalanceDetailService.remove(balanceWrapper);
//        // 删除司机记录
//        boolean b = driversService.removeById(driverId);
//        if (!b) {
//            return ResponseResult.fail("注销失败，请联系客服");
//        }
//        StpUtil.logout(driverId); // 注销会话
//        return ResponseResult.success("注销成功");
//    }
    /*=================================================================================*/

    @Logs(operation = "司机提交审核资料")
    @PostMapping("/saveReview")
    @RepeatSubmit
    public ResponseResult<DriverReview> saveReview(@RequestBody DriverReview driverReview) {
        driversReviewService.saveOrUpdate(driverReview);
        return ResponseResult.success("资料提交成功。");
    }

    //@Logs(operation = "创建手机验证码")
    @GetMapping("/createVerifyCode")
    @Release
    public ResponseResult<Integer> createVerifyCode(String phone) {
        //int verifyCode = driversService.createVerifyCode(phone);
        int verifyCode = 8888;
        //boolean b = driversService.sendMsm(phone, verifyCode);
        //if(b){
            return ResponseResult.success("验证码生成成功。8888", verifyCode);
        //}
        //return ResponseResult.fail("验证码生成失败，请稍后再试。");
    }

    //@Logs(operation = "根据司机id获取审核资料")
    @GetMapping("/getReviewByDriver")
    public ResponseResult<List<DriverReview>> getReviewByDriver(Integer driverId) {
        LambdaQueryWrapper<DriverReview> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DriverReview::getDriverId, driverId);
        List<DriverReview> list = driversReviewService.list(queryWrapper);

        return ResponseResult.success("查询成功", list);
    }

    //@Logs(operation = "根据id获取审核资料")
    @GetMapping("/getReviewById")
    public ResponseResult<DriverReview> getReviewById(Integer id) {
        DriverReview one = driversReviewService.getById(id);
        if (one == null) {
            return ResponseResult.fail("查不到数据，请重试。");
        }
        return ResponseResult.success("查询成功", one);
    }

    @PostMapping("/updateDriverAddr")
    public ResponseResult<Void> setDriverAddr(@RequestBody Driver driver) {
        driver.setId(UserOrDriverIdHolder.getDriverId());
        driversService.setDriverAddr(driver);
        return ResponseResult.success("更新司机位置");
    }

    /**
     * 根据token查询司机账号信息
     */
    @GetMapping("/info")
    public ResponseResult<Driver> getInfo() {
        Integer driverId = UserOrDriverIdHolder.getDriverId();
        Driver driver = driversService.getById(driverId);
        if (driver == null) {
            throw new RuntimeException("参数异常");
        }
        return ResponseResult.success(driver);
    }

    /**
     * 根据id查询司机姓氏
     */
    @GetMapping("/getSurnameById")
    @Release
    public ResponseResult<String> getSurnameById(@RequestParam Integer id) {
        Driver driver = driversService.getById(id);
        if (driver == null) {
            return ResponseResult.fail("司机不存在");
        }
        return ResponseResult.success("查询成功", driver.getSurname());
    }

    @GetMapping("/getOnlineDriver")
    @Release
    public ResponseResult<Integer> getOnlineDriver() {
        LambdaQueryWrapper<Driver> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Driver::getStatus, StatusConstants.DRIVER_ONLINE);

        List<Driver> list = driversService.list(lambdaQueryWrapper);
        return ResponseResult.success(list.size());
    }

    @GetMapping("/getDriverAddr")
    public ResponseResult<List<Map<Object, Object>>> getDriverAddr() {
        List<Map<Object, Object>> allDriverAddr = driversService.getAllDriverAddr();
        return ResponseResult.success(allDriverAddr);
    }

    @DeleteMapping("/deleteDriverAddr")
    public ResponseResult<Integer> deleteDriverAddr(Integer driverId) {
        driversService.removeDriverAddr(driverId);
        return ResponseResult.success();
    }

    @GetMapping("/getDriverIncomes")
    public ResponseResult<IncomesVo> getDriverIncomes() {
        IncomesVo driverIncomes = driverBalanceDetailService.getDriverIncomes(UserOrDriverIdHolder.getDriverId());

        return ResponseResult.success(driverIncomes != null ? driverIncomes : new IncomesVo());
    }

    @GetMapping("/getMyChildrenPage")
    public ResponseResult<Page<ChildrenDriverVo>> getMyChildrenList(@RequestParam(defaultValue = "1") int pageNum,
                                                                    @RequestParam(defaultValue = "10") int pageSize) {
        // 查分页
        Page<Driver> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Driver> qw = new LambdaQueryWrapper<Driver>()
                .eq(Driver::getPid, UserOrDriverIdHolder.getDriverId())
                .orderByDesc(Driver::getId);
        Page<Driver> driverPage = driversService.page(page, qw);
        // 拷贝数据
        Page<ChildrenDriverVo> res = new Page<>();
        BeanUtils.copyProperties(driverPage, res);
        List<ChildrenDriverVo> records = CustomBeanUtil.copyProperties(driverPage.getRecords(), ChildrenDriverVo.class);
        res.setRecords(records);

        res.getRecords().forEach(child -> {
            if (child.getAuditStatus() != StatusConstants.DRIVER_RECEIVE_PASS) {
                child.setTotalIncome(0L);
                child.setCommissionIncome(0L);
            } else {
                // 孩子的总收益
                LambdaQueryWrapper<DriverBalanceDetail> qw1 = new LambdaQueryWrapper<>();
                qw1.eq(DriverBalanceDetail::getDriverId, child.getId())
                        .in(DriverBalanceDetail::getBalanceType,
                                Arrays.asList(StatusConstants.BALANCE_TYPE_DRIVE_INCOME, StatusConstants.BALANCE_TYPE_REFUND_EXPENDITURE))
                        .select(DriverBalanceDetail::getAmount, DriverBalanceDetail::getBalanceType)
                ;
                List<DriverBalanceDetail> list1 = driverBalanceDetailService.list(qw1);
                long totalIncome = 0L;
                for (DriverBalanceDetail detail : list1) {
                    totalIncome += StatusConstants.BALANCE_TYPE_DRIVE_INCOME == detail.getBalanceType() ? detail.getAmount() : -detail.getAmount();
                }
                child.setTotalIncome(totalIncome);
                // 孩子为我带来的收益
                LambdaQueryWrapper<DriverBalanceDetail> qw2 = new LambdaQueryWrapper<>();
                qw2.eq(DriverBalanceDetail::getDriverId, UserOrDriverIdHolder.getDriverId())
                        .eq(DriverBalanceDetail::getChildId, child.getId())
                        .in(DriverBalanceDetail::getBalanceType,
                                Arrays.asList(StatusConstants.BALANCE_TYPE_CHILD_INCOME, StatusConstants.BALANCE_TYPE_CHILD_EXPENDITURE))
                        .select(DriverBalanceDetail::getAmount, DriverBalanceDetail::getBalanceType)
                ;
                List<DriverBalanceDetail> list2 = driverBalanceDetailService.list(qw2);
                long commissionIncome = 0L;
                for (DriverBalanceDetail detail : list2) {
                    commissionIncome += StatusConstants.BALANCE_TYPE_CHILD_INCOME == detail.getBalanceType() ? detail.getAmount() : -detail.getAmount();
                }
                child.setCommissionIncome(commissionIncome);
            }
        });
        // 返回结果
        return ResponseResult.success(res);
    }
}
